<?php
/*
 * Métodos de almacenamiento de los ficheros
 */

/*
 * Proceso de almacenamiento de varios ficheros
 */

function almacenar_ficheros($tmpfich) {
	global $_POST, $db, $rutaFicheros;
	$ficheros = array();
	$errores = array();


	/*
	echo '<pre>';
	var_dump($tmpfich);
	var_dump($_POST);
	echo '</pre>';
	 */

	/* Pasos a seguir:
	 *  1. Comprobar los errores que pueda haber, eliminando de la
	 *     subida los ficheros con error
	 *  2. Comprobar que todas las claves se han especificado
	 *  3. Comprobar que el nombre no está ya ocupado
	 *  4. Copiar el fichero al directorio
	 *  5. Añadir en la BD la información relativa al fichero
	 */

	// Pasos 1 + 2

	$ficherosBruto = count($tmpfich['name']);
	for ($i=0;$i<$ficherosBruto;$i++) {
		// No hay errores
		if ($tmpfich['error'][$i] == 0) {
			// ¿Tiene clave?
		   if (empty($_POST['clave'][$i])) {
				$errores[$i] = 'Clave no especificada.';
			} else {
				$ficheros[$i] = array(
					'name' => $tmpfich['name'][$i],
					'type' => $tmpfich['type'][$i],
					'tmp_name' => $tmpfich['tmp_name'][$i],
					'size' => $tmpfich['size'][$i],
					'descripcion' => $_POST['descripcion'][$i],
					'clave' => $_POST['clave'][$i]);
			}
		} else {
			$errores[$i] = traduce_error_subida($tmpfich['error'][$i]);
		}
	}
	// XXX: ¿Parar si hay errores, o subir los que no lo den? De 
	// momento, lo segundo.


	foreach ($ficheros as $fichero) {
		// Paso 3. ¿Nombre ocupado? Si lo está, añadir un prefijo al nombre 
		// del fichero, teniendo cuidado con la extensión
		// XXX: ¿Tener cuidado con el nombre del fichero?
		$fichero['name'] = solucionaConflictoNombre($fichero['name']);
		
		// Paso 4. Copia física de los ficheros sin errores
		if (is_uploaded_file($fichero['tmp_name'])) {
			if (!copy($fichero['tmp_name'], $rutaFicheros.'/'.$fichero['name'])) {
				// XXX Log
				echo 'Error copiando';
			} else {
				// Paso 5. SQL
				$tam = $fichero['size']/1024.0;
				$q = sprintf("INSERT INTO ficheros "
					."(nombre, descripcion,clave,iporigen,fecha,tamkb,mimetype) "
					."VALUES ('%s', '%s', '%s', '%s', '%d', '%f', '%s')",
						$db->escape($fichero['name']),
						$db->escape($fichero['clave']),
						$_SERVER['REMOTE_ADDR'],
						time(),
						$tam,
						mime_content_type($fichero['tmp_name']));
				$db->query($q);
				echo "Guardado";
			}
			// XXX Log también
		} else {
			// Algo raro hay...
			// XXX Log y aviso
		}

	}



	return array(
		'ficheros' => $ficheros,
		'errores' => $errores);
}

/*
 * Cuenta el número de ficheros válidos (con nombre no vacío)
 * que hay en el array $ficheros
 */

function ficheros_validos($ficheros) {
	 $ficherosBruto = count($ficheros['name']);
	 for ($numficheros = 0, $i=0;$i < $ficherosBruto;$i++) {
		 if (!empty($ficheros['name'][$i])) {
			 $numficheros++;
		 }
	 }

	 return $numficheros;
}

/*
 * Traduce los errores de un array de envío de ficheros
 */

function traduce_error_subida($err) {
	global $tamanoMaximo;

	switch($err) {
	case 1 : 
	case 2 : 
		return "El fichero es demasiado grande. El límite está en ".readable_size($tamanoMaximo)." por fichero.";
	case 3 : 
		return "No se llegó a enviar el fichero totalmente. Se descarta.";
	case 4 :
		return "No se envió ningún fichero.";
	case 6 : 
		return "Error grave: no hay directorio temporal.";
	case 7 : 
		return "Fallo al escribir en disco.";
	case 8 : 
		return "Extensión inadecuada para el fichero.";
	}
}

/*
 * Si el nombre de fichero ya está en la BD, busca un nuevo nombre 
 * teniendo cuidado con la extensión. Si no existe, lo devuelve tal cual
 */

function solucionaConflictoNombre($nombre) {
	global $db;
	$solucionado = FALSE;
	$nuevonombre = $nombre;

	while (!$solucionado) {
		$q = sprintf("SELECT nombre FROM ficheros WHERE nombre='%s'",
			$db->escape($nuevonombre));
		$res = $db->get_var($q);
		if (!$res) {
			$solucionado = TRUE;
		} else {

			// Partimos el nombre separando por los puntos.
			$tmp = explode(".", $res);
			// Buscamos el último punto o el penúltimo (para ficheros 
			// con doble extensión: .tar.gz, por ejemplo).
			$trozos = count($tmp);
			if ($trozos > 2) {
				$indice = $trozos-3;
			} else {
				$indice = 0;
			}

			// Añadimos '_' al final de este trozo
			$tmp[$indice] .= '_';

			$nuevonombre = implode(".", $tmp);

			// Evitamos nombres más largos de 255 caracteres (hemos 
			// estado añadiendo más caracteres detrás).
			if (strlen($nuevonombre) > 254) {
				$posiblenuevo = preg_replace('/_+\./g', '_1\.', $nuevonombre);
				if (strlen($posiblenuevo) > 254 || $posiblenuevo == $nuevonombre) {
					// No se me ocurre otra manera de acortar que coger 
					// los primeros 15 caracteres y ponerle la extensión 
					// que tuviera.
					$nuevonombre = substr($posiblenuevo, 0, 15).'_muylargo_'
						.$tmp[$trozos-1];
				} else {
					$nuevonombre = $posiblenuevo;
				}
				
			}
		}
	}

	return $nuevonombre;
}

?>
